import json
from datetime import datetime

from decimal import Decimal

from django import http
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render

# Create your views here.
from django.views import View
from django_redis import get_redis_connection

from apps.goods.models import SKU
from apps.orders.models import OrderInfo, OrderGoods
from apps.users.models import Address
from meiduo_mall.settings.dev import logger
from utils.response_code import RETCODE


class CommitView(LoginRequiredMixin,View):
    def post(self,request):
        #接收参数
        json_dict =json.loads(request.body.decode())
        address_id = json_dict.get('address_id')
        pay_method = json_dict.get('pay_method')
        #检验参数
        if not all([address_id, pay_method]):
            return http.HttpResponseForbidden('缺少必传参数')
        try:
            address = Address.objects.get(id = address_id)
        except Address.DoesNotExist:
            return http.HttpResponseForbidden('address_id无效')
        if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'],OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return http.HttpResponseForbidden("暂时不支持其他支付方式")
        #生成订单数据   生成订单号：年月日时分秒+用户编号
        user = request.user
        order_id = datetime.now().strftime('%Y%m%d%H%M%S') + "%09d" % user.id   #根据用户ID进行填充
        #创建订单商品的数据信息

        #使用事务保存订单
        from django.db import transaction
        #设置失误起点
        with transaction.atomic():
            #事务保存点
            save_id = transaction.savepoint()
            try:
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=address,
                    total_count=0,
                    total_amount=Decimal('0.00'),
                    freight=Decimal('10.00'),
                    pay_method=pay_method,            #未支付
                    status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method == OrderInfo.PAY_METHODS_ENUM['ALIPAY'] else
                    OrderInfo.ORDER_STATUS_ENUM['UNSEND']   #待收货
                )

                # 保存订单商品信息
                # 购物车里面   取出  选中的商品
                redis_client = get_redis_connection('carts')
                carts_data = redis_client.hgetall(user.id)
                carts_dict = {}
                for key,value in carts_data.items():
                    sku_id  = int(key.decode())
                    sku_dict = json.loads(value.decode())
                    if sku_dict['selected']:
                        carts_dict[sku_id] = sku_dict
                sku_ids = carts_dict.keys()
                for sku_id in sku_ids:

                    while True:
                        sku = SKU.objects.get(id=sku_id)

                        #原始销量  和 库存量
                        origin_sales = sku.sales
                        origin_stock = sku.stock

                        #判断库存  如果库存  小于 购买个数  购买失败
                        carts_count = carts_dict[sku_id]['count']

                        if carts_count > sku.stock:

                            #事务回滚
                            transaction.savepoint_rollback(save_id)
                            return http.JsonResponse({'code': RETCODE.STOCKERR, 'errmsg': '库存不足'})

                        #sku库存减少  销量增加
                        # sku.stock -= carts_count
                        # sku.sales += carts_count
                        # sku.save()

                        # ##模拟资源抢夺
                        import time
                        time.sleep(10)

                        #使用乐观锁  更新库存量
                        new_stock = origin_stock - carts_count
                        new_sales = origin_sales + carts_count

                        result = SKU.objects.filter(id=sku_id,stock=origin_stock).update(stock=new_stock,sales=new_sales)

                        if result == 0:
                            continue
                        #spu 销量增加
                        sku.spu.sales += carts_count
                        sku.spu.save()

                        #创建订单商品数据(多个)
                        OrderGoods.objects.create(
                            order_id = order_id,
                            sku = sku,
                            count = carts_count,
                            price =sku.price
                        )
                        #总个数 和 总金额
                        order.total_count += carts_count
                        order.total_amount += sku.price * carts_count

                        #下单成功 或 失败跳出
                        break
                #加运费  总金额
                order.total_amount += order.freight
                order.save()

            except Exception as e:
                logger.error(e)
                # 暴力回滚
                transaction.savepoint_rollback(save_id)
                return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '下单失败'})
            #事务提交   4张表都没问题
            transaction.savepoint_commit(save_id)
        # 清空购物车  清除已经结算过的商品
        redis_client.hdel(user.id, *carts_dict)
        #返回响应对象
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '下单成功', 'order_id': order.order_id})


class OrderSettlementView(LoginRequiredMixin,View):
    def get(self,request):
        #获取登陆用户   收货地址
        user = request.user
        try:
            addresses = Address.objects.filter(user = user,is_deleted=False)
        except Exception as e:
            addresses = None
        #查询选中商品  从redis里面选择出来所有的 购物车的数据
        redis_client = get_redis_connection('carts')
        carts_data = redis_client.hgetall(user.id)

        carts_dict = {}
        for key,value in carts_data.items():
            sku_key = int(key.decode())
            sku_dict = json.loads(value.decode())

            #选中状态
            if sku_dict['selected']:
                carts_dict[sku_key] = sku_dict
        skus = SKU.objects.filter(id__in = carts_dict.keys())

        #总个数
        total_count = 0
        #总金额
        total_amount = Decimal('0.00')
        for sku in skus:
            sku.count = carts_dict[sku.id]['count']
            sku.amount = sku.price * sku.count
            total_count +=sku.count
            total_amount += sku.amount
        #运费  固定十元
        freight = Decimal('10.00')
        # 4. context :
        context = {
            'addresses': addresses,
            'skus': skus,
            'total_count': total_count,
            'total_amount': total_amount,
            'freight': freight,

            'payment_amount': total_amount + freight,
            'default_address_id': user.default_address_id
        }

        return render(request,'place_order.html',context)

class SuccessView(LoginRequiredMixin,View):
    def get(self,request):
        order_id = request.GET.get('order_id')
        payment_amount = request.GET.get('payment_amount')
        pay_method = request.GET.get('pay_method')

        context = {
            'order_id': order_id,
            'payment_amount': payment_amount,
            'pay_method': pay_method
        }
        return render(request, 'order_success.html', context)

#订单页显示
class OrdersInfoView(View):
    def get(self,request,page_num):
        orders = request.user.orderinfo_set.all().order_by('-create_time')
        #遍历订单
        for order in orders:
            #查询订单的属性
            order.sku_list = []
            #查询订单商品     关联查询related_name之后 _set被related_name代替
            order_goods =order.skus.all()
            for order_good in order_goods:
                sku = order_good.sku
                sku.count = order_good.count
                sku.amount = sku.price * sku.count
                order.sku_list.append(sku)
            #订单的状态
            order.status_name = OrderInfo.ORDER_STATUS_CHOICES[order.status -1][1]
            #支付方式
            order.paymethod = OrderInfo.PAY_METHOD_CHOICES[order.pay_method -1][1]
        from django.core.paginator import Paginator
        paginator = Paginator(orders, 2)  # 实例化
        try:
            page_orders = paginator.page(page_num)  # 当前页数据
        except:
            return http.HttpResponseNotFound("empty page")

        total_pages = paginator.num_pages  # 总页数
        context = {
            'page_orders': page_orders,  # 分页后数据
            'total_page': total_pages,  # 总页数
            'page_num': page_num,  # 当前页码
        }
        return render(request,'user_center_order.html',context)

#订单评价
class OrdersCommentView(View):
    def get(self,request):
        order_id = request.GET.get('order_id')
        try:
            order = OrderInfo.objects.filter(order_id=order_id,user=request.user)
        except:
            return http.HttpResponseNotFound("订单不存在")
        try:
            ucomment_goods = OrderGoods.objects.filter(order_id=order_id,is_commented=False)
        except:
            return http.HttpResponseForbidden("无未评论订单")
        #遍历未评论的订单商品
        uncomment_goods_list = []
        for goods in ucomment_goods:
            uncomment_goods_list.append({
                'order_id': goods.order.order_id,
                'sku_id': goods.sku.id,
                'name': goods.sku.name,
                'price': str(goods.price),
                'default_image_url': goods.sku.default_image.url,
                'comment': goods.comment,
                'score': goods.score,
                'is_anonymous': str(goods.is_anonymous),  #是否匿名
            })
        context = {
            'uncomment_goods_list':uncomment_goods_list,
        }
        return render(request,'goods_judge.html',context)
    def post(self,request):
        json_dict = json.loads(request.body.decode())
        order_id = json_dict.get('order_id')
        sku_id = json_dict.get('sku_id')
        score = json_dict.get('score')
        comment = json_dict.get('comment')
        is_anonymous = json_dict.get('is_anonymous')  #是否匿名
        if not all([order_id,sku_id,comment]):
            return http.JsonResponse({'code': RETCODE.NECESSARYPARAMERR, 'errmsg': '缺少必须的参数'})
        try:
            OrderInfo.objects.get(order_id=order_id,user=request.user,
                                  status=OrderInfo.ORDER_STATUS_ENUM['UNCOMMENT'])
        except:
            return http.JsonResponse({'code': 5003, 'errmsg': '无匹配数据'})
        try:
            sku= SKU.objects.get(id=sku_id)
        except:
            return http.JsonResponse({'code': 5003, 'errmsg': '无匹配数据'})
        if not isinstance(is_anonymous,bool):
            return http.JsonResponse({'code': RETCODE.PARAMERR, 'errmsg': '参数错误'})
        #保存商品订单评价数据
        OrderGoods.objects.filter(order_id=order_id,sku_id=sku_id,is_commented=False).update(
            comment = comment,
            score = score,
            is_anonymous = is_anonymous,
            is_commented = True   #评价
        )
        #累计评价数据
        sku.comments +=1
        sku.spu.comments +=1
        sku.save()
        sku.spu.save()
        # 修改订单状态

        #订单商品的未被评论的个数==0：商品都评论过   同时修改商品信息表里面的商品的状态（是否评论）
        if OrderGoods.objects.filter(order_id=order_id,is_commented=False).count()==0:
            OrderInfo.objects.filter(order_id=order_id).update(status=OrderInfo.ORDER_STATUS_ENUM['FINISHED'])
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '评价成功'})


